package controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import modelInterfaces.IResult;
import modelInterfaces.ITest;
import pluginInterfaces.IMetric;
import utils.Codes;
import utils.Messages;
import utils.JFileChooserClass;
import utils.Validations;
import viewInterfaces.AbstractViewFactory;
import viewInterfaces.IViewSaveTestResult;
import controllerInterfaces.IControllerSaveTestResult;

/**
 * Controller class to establish the parameters of the CSV file with the test results.
 * 
 * @author Andy Cullache
 */
public class ControllerSaveTestResult implements IControllerSaveTestResult{
	
	private IViewSaveTestResult view;
	private List<ITest> tests;
	
	/**
	 * Default constructor.
	 */
	public ControllerSaveTestResult(){
		view = AbstractViewFactory.getAbstractViewFactory().getSaveTestResultView();
		view.setController(this);
	}
	
	/**
	* Returns the list of available tests, corresponds to the same list that appears in the benchmark panel.
	* 
	* @return      list of available tests.
	*/
	public List<ITest> getTests() {
		return tests;
	}
	
	/**
	* Establishing the list of tests from the project to this controller.
	* 
	* @param      tests list from current project.
	*/
	public void setTests(List<ITest> tests) {
		this.tests = tests;
	}
	
	/**
	* Opens a view to set the directory and name of the tests CSV file.
	* 
	* @return      a set of "String" size 2, contains the name and path of the CSV file.
	*/
	public String[] selectDirectory(){
		return JFileChooserClass.selectFileDirectoryToSave("RBox Result file",".csv","Save Test: Select directory");
	}
	
	/**
	* Opens a view to set the directory and name of the tests CSV file.
	* 
	* @param      test containing the results to save.
	* @return      True if file is written, false otherwise.
	*/
	public boolean writeTest (ITest test){
		if(Validations.isValidTestWrite(test)){
			PrintWriter writer = null;
			try {
				writer = writeTestToCSV(test);
			} catch (IOException e) {
				e.printStackTrace();
			}
			writer.print("Test Name" + ",");
			writer.print("Algorithm Name" + ",");
			writer.print("Subject" + ",");
			writer.print("N Recommender");
			for(IMetric metric : test.getMetrics()){
				writer.print(","+metric.toString());
			}
			
			int numMetrics = test.getMetrics().size();
			int aux = numMetrics;

		    for(String keyRecom : test.getResultMap().keySet()){				
				for(IResult resM : test.getResultMap().get(keyRecom)){
					if(aux == numMetrics){
						writer.println();
						writer.print(test.getName() + ",");
						writer.print(keyRecom + ",");
						writer.print(resM.getSubject() + ",");
						writer.print(resM.getVariable());
						aux = 0;
					}
					writer.print(","+resM.getResultAverage());
					aux++;
				}
			}
	
		    writer.flush();
	        return true;
        }
		else{
			view.renderError(Codes.errorSaveTestResult, Messages.errorSaveTestResult);
			return false;
		}
	}

	/**
	* Method that creates the CSV file containing the results (empty file) is occupied 
	* in the method writes the results (method "writeTest ()").
	* 
	* @param      test containing the results to save.
	* @return      objeto PrintWriter to write to the CSV file.
	*/
	private PrintWriter writeTestToCSV(ITest test) throws IOException{
    	
    	File dir = new File(test.getDirPath());
        if( !dir.exists() || !dir.isDirectory())
        {
            dir.mkdirs();
        }
        
        File file = new File( dir, test.getOutputFile() + ".csv");
        if( file.exists() )
        {
            boolean fileBackedUp = false;
            int count = 0;
            while( !fileBackedUp )
            {
                count++;
                File backup = new File(dir, test.getOutputFile() + ".bak-" + count );
                if( backup.exists() )
                {
                    continue;
                }

                boolean renamed = file.renameTo(backup);
                if( !renamed )
                {
                    System.out.println("Unable to rename file '" + file.getName() + "' to '" + backup.getName() + "'" );
                }
                else
                {
                    file = new File(dir, test.getOutputFile() + ".csv");
                    file.createNewFile();
                }
                break;
            }
        }
        
        FileOutputStream os = new FileOutputStream(file);
        return new PrintWriter(os);    
    }
}
